package com.sduept.nwld.dataserver.controller.fault;

import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.lang3.StringUtils;
import org.primefaces.event.FileUploadEvent;
import org.primefaces.model.StreamedContent;
import org.primefaces.model.UploadedFile;
import org.springframework.beans.factory.annotation.Autowired;

import com.sduept.bigdata.fault.entity.FaultRecord;
import com.sduept.bigdata.fault.entity.FaultRecordAttachment;
import com.sduept.bigdata.fault.entity.FaultReportComponentDetail;
import com.sduept.bigdata.fault.entity.FaultReportStationDetail;
import com.sduept.bigdata.fault.manager.CompentLibraryTransferDetailsManager;
import com.sduept.bigdata.fault.manager.FaultEditLockManager;
import com.sduept.bigdata.fault.manager.FaultRecordAttachmentManager;
import com.sduept.bigdata.fault.manager.FaultSourcePersistManager;
import com.sduept.bigdata.fault.model.DeviceActionProcessDTO;
import com.sduept.bigdata.fault.system.properties.FaultSystemProperties;
import com.sduept.nwld.dataserver.manager.fault.FaultRecordAttachmentAssistManager;
import com.sduept.permission.manager.PersonnelManager;

/**
 * 故障报告数据编辑抽象类 主要提供：图片的上传方法。
 * 初始化：需要在faultId,stationId1,stationId2赋值，并调用generateWaveEquipmentList方法
 * ，获得录波设备列表。
 */
public class FaultReportEditAbstractController extends ProtectActSvgController {

	/**
	 *
	 */
	private static final long serialVersionUID = 8652291572999233795L;
	@Autowired
	private FaultSystemProperties pros;
	@Autowired
	private FaultRecordAttachmentManager attManager;
	@Autowired
	private FaultRecordAttachmentAssistManager assManager;
	@Autowired
	protected CompentLibraryTransferDetailsManager transferManager;
	@Autowired
	private FaultEditLockManager lockM;
	@Autowired
	private PersonnelManager personM;
	@Autowired
	private FaultSourcePersistManager fspm;
	/**
	 * 录波文件上传和下载
	 */
	public static final String FILE_FORMAT_CFG = "cfg";
	public static final String FILE_FORMAT_DAT = "dat";
	// 对话框上传的文件列表
	public List<UploadedFile> uploadedFileList = new ArrayList<UploadedFile>();
	public Map<String, List<UploadedFile>> uploadFileMap = new HashMap<>();

	public String faultId;
	public String stationId1;
	public String stationId2;
	public StreamedContent file;

	public Boolean showBackButton = null;
	public int timingInteval = 5000;

	public List<FaultRecordAttachment> attachments1 = new ArrayList<FaultRecordAttachment>();
	public List<FaultRecordAttachment> selectedAttachments1 = new ArrayList<FaultRecordAttachment>();
	public List<FaultRecordAttachment> attachments2 = new ArrayList<FaultRecordAttachment>();
	public List<FaultRecordAttachment> selectedAttachments2 = new ArrayList<FaultRecordAttachment>();

	public void initBackButton() {
		if (showBackButton == null) {
			showBackButton = "true".equals(getParameter("showBackButton"));
		}
	}

	/**
	 * 加载附件列表
	 *
	 * @param faultRecord
	 */
	public void loadAttachmentList(FaultRecord faultRecord, String stationId1, String stationId2) {
		if (StringUtils.isNotBlank(stationId1)) {
			attachments1 = attManager.findByFaultIdAndStationId(faultRecord.getId(), stationId1);
		}
		if (StringUtils.isNotBlank(stationId2)) {
			attachments2 = attManager.findByFaultIdAndStationId(faultRecord.getId(), stationId2);
		}
	}
	/**
	 * 异步更新故障源元件上送信息
	 */
	protected void ayncUpdateActionUploadInfo(String frid) {
		fspm.ayncUpdateActionUploadInfo(frid);
	}
	/**
	 * 异步更新故障源录波上送信息
	 */
	protected void ayncUpdateWaveUploadInfo(String frid,String eid,String fileName) {
		fspm.ayncUpdateWaveUploadInfo( frid, eid,fileName);
	}
	/**
	 * 上传附件
	 *
	 * @param event
	 */
	public FaultRecordAttachment handleFileUpload(FileUploadEvent event, String stationId) {
		UploadedFile file = event.getFile();
		String fileName = file.getFileName();
		// 检查文件名是否已存在
		List<FaultRecordAttachment> as = new ArrayList<>();
		if (StringUtils.isNoneBlank(stationId1) && stationId1.equals(stationId)) {
			as = attachments1;
		} else if (StringUtils.isNoneBlank(stationId2) && stationId2.equals(stationId)) {
			as = attachments2;
		}
		for (FaultRecordAttachment f : as) {
			if (fileName.equals(f.getName())) {
				addErrorMessage("文件名已存在！文件上传失败！");
				return null;
			}
		}
		FaultRecordAttachment ra = assManager.handleFileUpload(file, faultId, stationId);
		if (ra == null) {
			addErrorMessage("附件上传失败！");
		} else {
			if (StringUtils.isNoneBlank(stationId1) && stationId1.equals(stationId)) {
				attachments1.add(ra);
			} else if (StringUtils.isNoneBlank(stationId2) && stationId2.equals(stationId)) {
				attachments2.add(ra);
			}
			addSuccessMessage("附件上传成功，请确认");
		}
		return ra;
	}

	/**
	 * 下载附件时，调用此方法，得到zip文件流
	 *
	 * @param attachments
	 * @return
	 */
	public StreamedContent getAttachmentFile(String stationId) {
		List<FaultRecordAttachment> as = null;
		if (StringUtils.isNoneBlank(stationId1) && stationId1.equals(stationId)) {
			as = selectedAttachments1;
		} else if (StringUtils.isNoneBlank(stationId2) && stationId2.equals(stationId)) {
			as = selectedAttachments2;
		}
		if (as == null || as.size() == 0) {
			addErrorMessage("未选择下载内容");
			return null;
		}
		return assManager.getAttachmentFile(as);
	}

	public void deleteAttachment(String stationId) {
		if (StringUtils.isNoneBlank(stationId1) && stationId1.equals(stationId)) {
			assManager.deleteAttachment(selectedAttachments1);
		} else if (StringUtils.isNoneBlank(stationId2) && stationId2.equals(stationId)) {
			assManager.deleteAttachment(selectedAttachments2);
		}
	}

	/**
	 * 此方法用來合并数据库中的保护动作与字典表中的记录
	 * 
	 * @param fd
	 * @param componentList
	 * @param protectDeviceActionProcessList
	 * @param breakerDeviceActionProcessList
	 */
	public void unionComponentDetails(FaultRecord fd, List<FaultReportComponentDetail> componentList,
			List<DeviceActionProcessDTO> protectDeviceActionProcessList,
			List<DeviceActionProcessDTO> breakerDeviceActionProcessList) {
		List<DeviceActionProcessDTO> dtos = new ArrayList<DeviceActionProcessDTO>();
		for (DeviceActionProcessDTO dto : protectDeviceActionProcessList) {
			if (StringUtils.isEmpty(dto.getDevName())) {
				continue;
			}
			DeviceActionProcessDTO param = new DeviceActionProcessDTO();
			if ("线路".equals(fd.getEtype()) && "主保护".equals(dto.getDevType())) {
				param.setDevName("线路" + dto.getDevName());
			} else if ("断路器保护".equals(dto.getDevType())) {
				for (DeviceActionProcessDTO tmp : breakerDeviceActionProcessList) {
					if (dto.getDevName().contains(tmp.getDevName())) {
						dto.setDevName(tmp.getDevName() + "断路器保护");
						break;
					}
				}
			} else {
				param.setDevName(dto.getDevName());
			}
			param.setDevName(dto.getDevName());
			param.setDevModel(dto.getDevModel());
			param.setId(dto.getId());
			dtos.add(param);
		}
		ArrayList<FaultReportComponentDetail> tmpList = new ArrayList<FaultReportComponentDetail>();
		tmpList.addAll(componentList);
		List<FaultReportComponentDetail> list = transferManager.getUnionComponentDetails(tmpList, dtos,
				fd.getFaultType(), fd.getFaultPhase());
		if (null != list) {
			componentList.clear();
			componentList.addAll(list);
		}
	}

	/**
	 * 克隆动作元件列表
	 * 
	 * @param srcs
	 * @return
	 */
	public List<FaultReportComponentDetail> copyComponentDetails(List<FaultReportComponentDetail> srcs) {
		ArrayList<FaultReportComponentDetail> result = new ArrayList<FaultReportComponentDetail>();
		for (FaultReportComponentDetail detail : srcs) {
			FaultReportComponentDetail tmp = new FaultReportComponentDetail();
			try {
				BeanUtils.copyProperties(tmp, detail);
				result.add(tmp);
			} catch (IllegalAccessException | InvocationTargetException e) {
				e.printStackTrace();
				continue;
			}
		}
		return result;
	}

	/**
	 * 与原先的比较，有变化的数据改变其状态
	 * 
	 * @param dests
	 * @param srcs
	 */
	public void listCompareAndSave(List<FaultReportComponentDetail> dests, List<FaultReportComponentDetail> srcs) {
		for (FaultReportComponentDetail faultReportComponentDetail : dests) {
			compareAndSave(faultReportComponentDetail, srcs);
		}
	}

	private void compareAndSave(FaultReportComponentDetail detail, List<FaultReportComponentDetail> srcs) {
		if (detail.getDataLockStatus() != 0) {
			return;
		}
		boolean exist = false;
		for (FaultReportComponentDetail tmp : srcs) {
			if (detail.getId().equals(tmp.getId())) {
				exist = true;
				boolean isSame = Objects.equals(tmp.getProtectName(), detail.getProtectName())
						&& Objects.equals(tmp.getProtectType(), detail.getProtectType())
						&& Objects.equals(tmp.getProtectModel(), detail.getProtectModel())
						&& Objects.equals(tmp.getActionComponent(), detail.getActionComponent())
						&& Objects.equals(tmp.getFunClassification(), detail.getFunClassification())
						&& Objects.equals(tmp.getActionTime(), detail.getActionTime())
						&& Objects.equals(tmp.getActionCondition(), detail.getActionCondition())
						&& Objects.equals(tmp.getRemark(), detail.getRemark());
				if (!isSame) {
					detail.setDataLockStatus(1);
				}
				break;
			}
		}
		if (!exist) {
			detail.setDataLockStatus(1);
		}
	}

	/**
	 * 获取资源使用者
	 * 
	 * @param faultStationId
	 * @return
	 */
	public String gainOwner(String faultStationId) {
		// TODO 用变电站id检查
		String ownerId = lockM.gainOwenr(faultStationId);
		if ("管理员".equals(ownerId)) {
			return ownerId;
		} else {
			return personM.findPersonnelById(ownerId).getName();
		}
	}

	/**
	 * 判断该变电站是否被占用
	 * 
	 * @param stationId
	 * @return
	 */
	public boolean checkEditPageIsUsed(String faultStationId) {
		// 该资源是否可用 true：可用 ; false：不可用
		return lockM.gainLock(faultStationId, new Date().getTime(), getCurrentUser().getId());
	}

	/**
	 * 顺序： 1.行波双端测距 2.行波单端测距 3.录波双端测距
	 * 
	 * @return
	 */
	protected List<Double> getStartAndEndDistances(FaultReportStationDetail firstStationDetail,FaultReportStationDetail secondStationDetail) {
		List<Double> distances = new ArrayList<>();
		Double startDistance =getBestestDistances(firstStationDetail.getTravelingWaveDouble(), firstStationDetail.getTravelingWave(), firstStationDetail.getManualRangingWave());
		Double endDistance =getBestestDistances(secondStationDetail.getTravelingWaveDouble(), secondStationDetail.getTravelingWave(), secondStationDetail.getManualRangingWave());
		distances.add(startDistance);
		distances.add(endDistance);
		return distances;
	}
	/**
	 * 获得最优的测距信息
	 * @param TravelingWaveDouble
	 * @param TravelingWave
	 * @param RangingWave
	 * @return
	 */
	private Double getBestestDistances(Double TravelingWaveDouble,Double TravelingWave,Double manualRangingWave) {
		if(TravelingWaveDouble!=null && TravelingWaveDouble>0) {
			return TravelingWaveDouble;
		}else if(TravelingWave!=null && TravelingWave>0) {
			return TravelingWave;
		}else if(manualRangingWave!=null && manualRangingWave>0) {
			return manualRangingWave;
		}else {
			return null;
		}
	}
	public String getVirtualPath(String path) {
		return pros.getFaultAttachmentPath() + path;
	}

	public boolean isPicture(FaultRecordAttachment m) {
		return assManager.isPicture(m.getSuffix());
	}

	public List<UploadedFile> getUploadedFileList() {
		return uploadedFileList;
	}

	public void setUploadedFileList(List<UploadedFile> uploadedFileList) {
		this.uploadedFileList = uploadedFileList;
	}

	public Map<String, List<UploadedFile>> getUploadFileMap() {
		return uploadFileMap;
	}

	public void setUploadFileMap(Map<String, List<UploadedFile>> uploadFileMap) {
		this.uploadFileMap = uploadFileMap;
	}

	public String getFaultId() {
		return faultId;
	}

	public void setFaultId(String faultId) {
		this.faultId = faultId;
	}

	public List<FaultRecordAttachment> getAttachments1() {
		return attachments1;
	}

	public void setAttachments1(List<FaultRecordAttachment> attachments1) {
		this.attachments1 = attachments1;
	}

	public List<FaultRecordAttachment> getSelectedAttachments1() {
		return selectedAttachments1;
	}

	public void setSelectedAttachments1(List<FaultRecordAttachment> selectedAttachments1) {
		this.selectedAttachments1 = selectedAttachments1;
	}

	public List<FaultRecordAttachment> getAttachments2() {
		return attachments2;
	}

	public void setAttachments2(List<FaultRecordAttachment> attachments2) {
		this.attachments2 = attachments2;
	}

	public List<FaultRecordAttachment> getSelectedAttachments2() {
		return selectedAttachments2;
	}

	public void setSelectedAttachments2(List<FaultRecordAttachment> selectedAttachments2) {
		this.selectedAttachments2 = selectedAttachments2;
	}

	public StreamedContent getFile() {
		return file;
	}

	public void setFile(StreamedContent file) {
		this.file = file;
	}

	public Boolean getShowBackButton() {
		return showBackButton;
	}

	public void setShowBackButton(Boolean showBackButton) {
		this.showBackButton = showBackButton;
	}

	public int getTimingInteval() {
		return timingInteval;
	}

	public void setTimingInteval(int timingInteval) {
		this.timingInteval = timingInteval;
	}

}
